<template>
  <lay-container fluid="true" class="file-box">
    <!-- 搜索区域 -->
    <lay-card>
      <lay-form style="margin-top: 10px">
        <lay-row>
          <lay-col :md="8">
            <lay-form-item label="文件名称" label-width="80">
              <lay-input v-model="searchQuery.remark" placeholder="请输入文件名称" size="sm" :allow-clear="true"
                style="width: 98%"></lay-input>
            </lay-form-item>
          </lay-col>
          <lay-col :md="8">
            <lay-form-item label="文件路径" label-width="80">
              <lay-input v-model="searchQuery.filePath" placeholder="请输入文件路径" size="sm" :allow-clear="true"
                style="width: 98%"></lay-input>
            </lay-form-item>
          </lay-col>
          <lay-col :md="8">
            <lay-form-item label-width="20">
              <lay-button style="margin-left: 20px" type="primary" size="sm" @click="toSearch">
                查询
              </lay-button>
              <lay-button size="sm" @click="toReset"> 重置 </lay-button>
            </lay-form-item>
          </lay-col>
        </lay-row>
      </lay-form>
    </lay-card>
    <!-- 文件列表区域 -->
    <div class="table-box">
      <lay-table :page="page" :height="'100%'" :columns="columns" :loading="loading" :default-toolbar="true"
        :data-source="dataSource" v-model:selected-keys="selectedKeys" @change="change" @sortChange="sortChange">
        <template #filePath="{ row }">
          <a class="file-link" :href="getFilePreviewUrl(row.filePath)" target="_blank" :title="row.filePath">
            {{ row.filePath }}
          </a>
        </template>

        <template #fileType="{ row }">
          <span>{{ row.fileType || '-' }}</span>
        </template>

        <template #createTime="{ row }">
          <span>{{ formatDateTime(row.createTime) }}</span>
        </template>
        <template v-slot:toolbar>
          <lay-button size="sm" type="primary" @click="toImport">
            <lay-icon class="layui-icon-upload-drag"></lay-icon>
            上传文件
          </lay-button>
          <lay-button size="sm" @click="toRemove">
            <lay-icon class="layui-icon-delete"></lay-icon>
            批量删除
          </lay-button>
        </template>
        <template v-slot:operator="{ row }">
          <lay-button size="xs" border="green" border-style="dashed" @click="toDownload(row)">下载</lay-button>
          <lay-popconfirm content="确定要删除此文件吗?" @confirm="confirm(row.fileId)" @cancel="cancel">
            <lay-button size="xs" border="red" border-style="dashed">删除</lay-button>
          </lay-popconfirm>
        </template>
      </lay-table>
    </div>
    <!-- 上传文件弹窗 -->
    <lay-layer v-model="visibleImport" title="上传文件" :area="['520px', '420px']" class="upload-modal">
      <div class="upload-content">
        <div class="upload-area">
          <lay-upload :beforeUpload="beforeUpload" :url="uploadUrl" :headers="uploadHeaders" v-model="fileList"
            field="file" :auto="false" :drag="true" :multiple="false" @done="uploadSuccess" @error="uploadError"
            class="upload-component" ref="uploadRef">
            <template #tip>
              <div class="upload-tip">
                <lay-icon type="layui-icon-tips" style="color: #ff9900; margin-right: 4px;"></lay-icon>
                支持上传各种类型的文件，单个文件大小不超过100MB
              </div>
            </template>
          </lay-upload>
        </div>

        <div v-if="fileList.length > 0" class="file-info">
          <div class="file-info-header">
            <lay-icon type="layui-icon-file" style="color: #1677ff; margin-right: 8px;"></lay-icon>
            <span>文件信息</span>
          </div>
          <div class="file-info-content">
            <div class="file-info-item">
              <span class="file-info-label">文件名：</span>
              <span class="file-info-value">{{ fileList[0]?.name }}</span>
            </div>
            <div class="file-info-item">
              <span class="file-info-label">文件大小：</span>
              <span class="file-info-value">{{ formatFileSize(fileList[0]?.size) }}</span>
            </div>
          </div>
        </div>

        <div class="upload-actions">
          <lay-button type="primary" size="sm" @click="handleUploadConfirm" class="confirm-btn">
            <lay-icon type="layui-icon-ok" style="margin-right: 4px;"></lay-icon>
            确认上传
          </lay-button>
          <lay-button size="sm" @click="handleUploadCancel" class="cancel-btn">
            <lay-icon type="layui-icon-close" style="margin-right: 4px;"></lay-icon>
            取消
          </lay-button>
        </div>
      </div>
    </lay-layer>
  </lay-container>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { layer } from '@layui/layui-vue'
import { queryLimit, delFile, uploadFile, downloadFile, deleteFile } from '@/api/module/file-manager'
import { getBaseUrl } from '@/api/http'
import { useUserStore } from '@/store/user'

const searchQuery = ref({
  filePath: '',
  remark: ''
})

const visibleImport = ref(false)
const fileList = ref<any>([])
const uploadUrl = ref(`${getBaseUrl()}/sysFile/api/upload`)
const uploadRef = ref()
const uploadHeaders = ref<any>(null)
const userInfoStore = useUserStore()

function toImport() {
  visibleImport.value = true
}

function toReset() {
  searchQuery.value = {
    filePath: '',
    remark: ''
  }
  page.current = 1
  loadData()
}

function toSearch() {
  page.current = 1
  loadData()
}

async function toDownload(row: any) {
  try {
    // 使用window.open直接打开下载链接，避免Blob处理
    const downloadUrl = `${getBaseUrl()}/sysFile/api/download?fileId=${row.fileId}`
    window.open(downloadUrl, '_blank')
    layer.msg('开始下载...')
  } catch (error) {
    layer.msg('下载失败，请重试', { icon: 2 })
  }
}

const loading = ref(false)
const selectedKeys = ref<string[]>([])
const page = reactive({ current: 1, limit: 10, total: 0 })
const columns = ref([
  { title: '选项', width: '60px', type: 'checkbox', fixed: 'left' },
  { title: '编号', width: '165px', key: 'id', fixed: 'left', sort: 'desc' },
  { title: '文件ID', key: 'fileId', width: '100px', sort: 'desc',hide: true },
  { title: '文件名称', key: 'remark', sort: 'desc' },
  { title: '文件路径', key: 'filePath', sort: 'desc',  ellipsisTooltip: true },
  { title: '文件类型', width: '120px', key: 'fileType', sort: 'desc' },
  { title: '创建时间', width: '180px', key: 'createTime', sort: 'desc' },
  {
    title: '操作',
    width: '150px',
    customSlot: 'operator',
    key: 'operator',
    fixed: 'right'
  }
])

const dataSource = ref([])

async function loadData() {
  loading.value = true
  try {
    const queryWhere = {
      pageIndex: page.current,
      pageSize: page.limit,
      requestBody: searchQuery.value
    }
    const response = await queryLimit(queryWhere)
    if (response.code === 200) {
      dataSource.value = response.data.responseBody || []
      page.total = response.data.totalNum || 0
    } else {
      layer.msg('获取数据失败', { icon: 2 })
    }
  } catch (error) {
    layer.msg('网络错误，请重试', { icon: 2 })
  } finally {
    loading.value = false
  }
}

const change = (pageInfo: any) => {
  page.current = pageInfo.current
  page.limit = pageInfo.limit
  loadData()
}

const sortChange = (key: any, sort: number) => {
  // 可以在这里实现服务端排序
  layer.msg(`字段${key} - 排序${sort}`)
}

function getFilePreviewUrl(filePath: string) {
  // 后端没有预览接口，对于图片文件直接返回文件路径，其他文件返回#
  if (filePath && (filePath.endsWith('.jpg') || filePath.endsWith('.png') || filePath.endsWith('.gif') || filePath.endsWith('.jpeg') || filePath.endsWith('.bmp') || filePath.endsWith('.webp'))) {
    return filePath
  }
  return '#'
}

async function toRemove() {
  if (selectedKeys.value.length == 0) {
    layer.msg('您未选择数据，请先选择要删除的数据', { icon: 3, time: 2000 })
    return
  }

  layer.confirm('您将删除所有选中的数据？', {
    title: '提示',
    btn: [
      {
        text: '确定',
        callback: async (id: any) => {
          try {
            const response = await delFile(selectedKeys.value)
            if (response.code === 200) {
              layer.msg('删除成功')
              loadData()
              selectedKeys.value = []
            } else {
              layer.msg('删除失败', { icon: 2 })
            }
          } catch (error) {
            layer.msg('删除失败，请重试', { icon: 2 })
          }
          layer.close(id)
        }
      },
      {
        text: '取消',
        callback: (id: any) => {
          layer.msg('您已取消操作')
          layer.close(id)
        }
      }
    ]
  })
}

async function confirm(fileId: string) {
  try {
    const response = await deleteFile(fileId)
    if (response.code === 200) {
      layer.msg('删除成功')
      loadData()
    } else {
      layer.msg('删除失败', { icon: 2 })
    }
  } catch (error) {
    layer.msg('删除失败，请重试', { icon: 2 })
  }
}

function cancel() {
  layer.msg('您已取消操作')
}

const beforeUpload = (file: any) => {
  // 可以在这里添加文件大小限制等验证
  const maxSize = 100 * 1024 * 1024 // 100MB
  if (file.size > maxSize) {
    layer.msg(`文件大小不能超过100MB`, { icon: 2 })
    return false
  }
  return true
}

function uploadSuccess(response: any) {
  const strBody = response.data;
  const jsonBody = JSON.parse(strBody);
  if (jsonBody.code === 200) {
    layer.msg('上传成功', { icon: 1 })
    // 延迟关闭弹窗，确保消息显示完整
    setTimeout(() => {
      visibleImport.value = false
      fileList.value = []
      loadData()
    }, 500)
  } else {
    layer.msg('上传失败', { icon: 2 })
  }
}

function uploadError(error: any) {
  layer.msg('上传失败，请重试', { icon: 2 })
}

async function handleUploadConfirm() {
  if (fileList.value.length === 0) {
    layer.msg('请先选择要上传的文件', { icon: 3 })
    return
  }

  // 手动触发上传组件的上传
  const uploadComponent = uploadRef.value
  if (uploadComponent && uploadComponent.submit) {
    // 设置上传Header，携带token认证信息
    uploadHeaders.value = {
      token: userInfoStore.token,
      clientId: userInfoStore.clientId
    }

    uploadComponent.submit()
  } else {
    layer.msg('上传组件未找到，请重试', { icon: 2 })
  }
}

function handleUploadCancel() {
  visibleImport.value = false
  fileList.value = []
}

function formatFileSize(bytes: number) {
  if (!bytes) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

function formatDateTime(dateTime: string) {
  if (!dateTime) return '-'
  return dateTime
}

onMounted(() => {
  loadData()
})
</script>

<style scoped>
.file-box {
  width: calc(100vw - 220px);
  height: calc(100vh - 110px);
  margin: 10px auto;
  box-sizing: border-box;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 8px; /* 减小卡片间距 */
}

/* 搜索区域固定高度 */
.search-form {
  padding: 20px;
  min-height: auto;
}

/* 表格容器固定高度，确保分页可见 */
.table-container {
  flex: 1;
  padding: 0 20px 20px 20px;
  display: flex;
  flex-direction: column;
  height: calc(100vh - 280px); /* 减去搜索区域和边距的高度 */
  min-height: 400px;
}

.file-table {
  flex: 1;
  height: 100%;
}

/* 确保表格内容区域不会溢出 */
:deep(.layui-table) {
  height: calc(100% - 60px); /* 减去表头和分页的高度 */
}

:deep(.layui-table-body) {
  max-height: none !important;
}

:deep(.layui-table-page) {
  position: relative;
  bottom: 0;
  margin-top: auto;
}

.search-card {
  background-color: #fff;
  border-radius: 4px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.search-header {
  display: flex;
  align-items: center;
  padding: 16px 20px;
  border-bottom: 1px solid #f0f0f0;
}

.search-icon {
  margin-right: 8px;
  color: #1677ff;
}

.search-title {
  font-size: 16px;
  font-weight: 600;
  color: #333;
}

.search-form {
  padding: 20px;
}

.search-buttons {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}

.table-card {
  flex: 1;
  background-color: #fff;
  border-radius: 4px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
}

.table-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid #f0f0f0;
}

.table-icon {
  margin-right: 8px;
  color: #1677ff;
}

.table-title {
  font-size: 16px;
  font-weight: 600;
  color: #333;
  flex: 1;
}

.table-toolbar {
  display: flex;
  gap: 8px;
}

.table-container {
  flex: 1;
  padding: 0 20px 20px 20px;
}

.file-table {
  height: 100%;
}

.file-link {
  color: #1677ff;
  text-decoration: none;
  cursor: pointer;
}

.file-link:hover {
  text-decoration: underline;
}

.upload-content {
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.upload-area {
  border: 2px dashed #d9d9d9;
  border-radius: 4px;
  padding: 20px;
  text-align: center;
  transition: border-color 0.3s;
}

.upload-area:hover {
  border-color: #1677ff;
}

.upload-tip {
  margin-top: 8px;
  color: #666;
  font-size: 12px;
}

.file-info {
  border: 1px solid #f0f0f0;
  border-radius: 4px;
  padding: 16px;
}

.file-info-header {
  display: flex;
  align-items: center;
  margin-bottom: 12px;
  font-weight: 600;
  color: #333;
}

.file-info-content {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.file-info-item {
  display: flex;
  align-items: center;
}

.file-info-label {
  width: 80px;
  color: #666;
}

.file-info-value {
  color: #333;
}

.upload-actions {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-top: 16px;
}

.search-input {
  display: inline-block;
  width: 98%;
  margin-right: 10px;
}
</style>